package com.tfjybj.itoo.teach.provider.service.impl;

import org.apache.dubbo.config.annotation.Reference;;
import com.dmsdbj.itoo.authorizationManagement.entity.OrganizationEntity;
import com.dmsdbj.itoo.authorizationManagement.facade.OrganizationFacade;
import com.dmsdbj.itoo.tool.base.service.impl.BaseServicePlusImpl;
import com.dmsdbj.itoo.tool.business.ItooResult;
import com.dmsdbj.itoo.tool.uuid.BaseUuidUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tfjybj.itoo.teach.entity.ProfessionEntity;
import com.tfjybj.itoo.teach.model.ProfessionModel;
import com.tfjybj.itoo.teach.provider.dao.ProfessionDao;
import com.tfjybj.itoo.teach.provider.service.AcademyService;
import com.tfjybj.itoo.teach.provider.service.ProfessionService;
import com.tfjybj.itoo.teach.provider.until.YearAcquisitionUtil;
import com.tfjybj.itoo.teach.template.ProfessionExportTemplate;
import com.tfjybj.itoo.teach.template.ProfessionTemplate;
import lombok.extern.slf4j.Slf4j;
import org.jplus.hyberbin.excel.utils.ExcelUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.*;

import static com.tfjybj.itoo.teach.provider.until.DemoConstants.*;

/**
 * ProfessionService接口实现类
 * ${base}表
 *
 * @author 田成荣
 * @version 2.0.0
 * @since 2.0.0 2018-11-08 19:34:10
 */
@Service("professionService")
@Slf4j
public class ProfessionServiceImpl extends BaseServicePlusImpl<ProfessionDao,ProfessionEntity> implements ProfessionService {

    @Resource
    private ProfessionService professionService;

    @Resource
    private AcademyService academyService;

    @Resource
    private RedisTemplate<String, ProfessionTemplate> redisTemplate;
	//region 模板生成
    @Resource
    private ProfessionDao professionDao;

    //@Autowired(required = false)
    //private OrganizationFacade organizationFacade;

    /**
     * 根据专业名称模糊查询profession
     *
     * @param name  专业名称
     * @param pageNum   页码
     * @param pageSize 页数
     * @return 模糊查询的profession
     * @author 田成荣
     * @since 2.0.0 2018-11-08 19:34:10
     */
    @Override
    public PageInfo<ProfessionEntity> queryByLikeName(String name, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new PageInfo<>(professionDao.queryLikeName(name));
    }
	//endregion

    /* **********************************以下为非模板生成的内容********************************* */
    /**
     * 根据教学部门id查询专业信息（带分页）
     * @param academyId 学院id
     * @author 杨燕梅
     * @since 2.0.0 2018-11-15 15:43:42
     */
    @Override
    public PageInfo<ProfessionModel>queryByAcademyIdPageInfo(String academyId,Integer pageNum,Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        return new PageInfo<>(professionDao.queryByAcademyId(academyId));
    }

    /**
     * 根据教学部门id查询专业信息
     * @param academyId 学院id
     * @author 杨燕梅
     * @since 2.0.0 2018-11-15 15:43:42
     */
    @Override
    public List<ProfessionModel>queryByAcademyId(String academyId) {
        return professionDao.queryByAcademyId(academyId);
    }

    /**
     * 根据专业名称查询professions
     * @param name  专业名称
     * @return 查询的profession
     * @author 田成荣
     * @since 2.0.0 2018-11-08 19:34:10
     */
    @Override
    public List<ProfessionModel> queryProfessionsByName(String name){
        return professionDao.queryByName(name);
    }

    /**
     * 查询所有专业层次
     *
     * @return nature  专业层次
     * @author 杨燕梅
     * @since 2.0.0 2018-11-28 14:59:20
     */
    @Override
    public List<ProfessionModel> queryAllNature(){
        return professionDao.queryAllNature();
    }

    /**
     * 查询所有学制
     *
     * @return schoolLength  学制
     * @author 杨燕梅
     * @since 2.0.0 2018-11-28 14:59:40
     */
    @Override
    public List<ProfessionModel>queryAllSchoolLength(){
        return professionDao.queryAllSchoolLength();
    }

    @Override
    public List<ProfessionEntity>queryAllProfession(){
        return professionDao.queryAllProfession();
    }

    /**
     * 根据专业名称模糊查询某一学院下属专业
     *
     * @param searchContent  专业名称
     * @param pageNum   页码
     * @param pageSize 页数
     * @param academyId 学院id
     * @return 模糊查询的某一学院下属专业
     * @author 杨燕梅
     * @since 2.0.0 2018-11-28 20:21:04
     */
    @Override
    public PageInfo<ProfessionModel> queryByLikeNameAndAcademyId(String academyId, Integer pageNum, Integer pageSize,String searchContent) {
        PageHelper.startPage(pageNum, pageSize);
        return new PageInfo<>(professionDao.queryByLikeNameAndAcademyId(academyId,searchContent.trim()));
    }

    /**
     * 根据专业ID查询专业详情
     *
     * @param idList 专业ID
     * @return 专业实体集合
     * @author 杨燕梅
     * @since 2.0.0 2018-12-12 20:10:09
     */
    @Override
    public List<ProfessionModel> queryProfessionById(List<String> idList) {
        return professionDao.queryProfessionById(idList);
    }

    /**
     * 根据ID导出专业信息
     *
     * @param response 响应
     * @param idList   专业ID
     * @return 导出结果信息
     * @author 杨燕梅
     * @since 2.0.0 2018-12-12 20:10:49
     */
    @Override
    public ItooResult exportByProfessionId(HttpServletResponse response, List<String> idList) {
        Map<Serializable, Serializable> map = new HashMap<>(16);

        map.put(SHEET_NAME, "导出的专业信息");
        //要导出的字段
        map.put(COLUMNS,   new String[]{"code", "name", "schoolLength", "nature", "academyName", "remark"});
        //导出表格的标题
        map.put(TITLE, "导出的专业信息");
        map.put(NAME, "导出的专业信息");
        //要导出的数据
        List<ProfessionExportTemplate> professionExportTemplateList = new ArrayList<>();

        List<ProfessionModel> professionModelList = professionDao.queryProfessionById(idList);
        for (ProfessionModel professionModel : professionModelList) {
            ProfessionExportTemplate professionExportTemplate = new ProfessionExportTemplate();
            BeanUtils.copyProperties(professionModel, professionExportTemplate);
            professionExportTemplateList.add(professionExportTemplate);
        }
        //为空不进行导出
        if (CollectionUtils.isEmpty(professionExportTemplateList)) {
            return ItooResult.build(ItooResult.FAIL, "没有要导出的数据！");
        }
        map.put(DATA_LIST, (Serializable) professionExportTemplateList);

        //导出
        try {
            ExcelUtil.exportExcel(map, response);
        } catch (Exception e) {
            log.error("导出失败,未知的异常--" + e);
            return ItooResult.build(ItooResult.FAIL, "导出信息失败！", e);
        }
        return ItooResult.build(ItooResult.SUCCESS, "导出信息成功！");
    }

    /**
     * 根据条件导出专业
     *
     * @param response     响应
     * @param searchContent    专业名称
     * @return 导出结果信息
     * @author 杨燕梅
     * @since 2.0.0 2018-12-23 16:49:39
     */
    @Override
    public ItooResult exportByStrLike(HttpServletResponse response, String academyId, String searchContent) {
        Map<Serializable, Serializable> map = new HashMap<>(16);
        map.put(SHEET_NAME, "专业");
        //要导出的字段
        map.put(COLUMNS,  new String[]{"code", "name", "schoolLength", "nature", "academyName", "remark"});
        //导出表格的标题
        map.put(TITLE, "专业信息");
        map.put(NAME, "按条件导出的专业信息");
        //要导出的数据
        List<ProfessionExportTemplate> professionExportTemplateList = new ArrayList<>();
        List<ProfessionModel> professionModelList = professionDao.queryByLikeNameAndAcademyId(academyId ,searchContent);
        for (ProfessionModel professionModel : professionModelList) {
            ProfessionExportTemplate professionExportTemplate = new ProfessionExportTemplate();
            BeanUtils.copyProperties(professionModel, professionExportTemplate);
            professionExportTemplateList.add(professionExportTemplate);
        }
        //为空不进行导出
        if (CollectionUtils.isEmpty(professionExportTemplateList)) {
            return ItooResult.build(ItooResult.FAIL, "没有要导出的数据！");
        }
        map.put(DATA_LIST, (Serializable) professionExportTemplateList);

        //导出
        try {
            ExcelUtil.exportExcel(map, response);
        } catch (Exception e) {
            log.error("导出失败,未知的异常--" + e);
            return ItooResult.build(ItooResult.FAIL, "导出信息失败！", e);
        }
        return ItooResult.build(ItooResult.SUCCESS, "导出信息成功！");
    }

    /**
     * 下载专业模板，批量导入使用
     *
     * @param response 响应
     * @return 下载模板是否成功
     * @author 杨燕梅
     * @since 2.0.0 2018-11-30 10:10:17
     */
    @Override
    public boolean downLoadTemplate(HttpServletResponse response) {
        Map<Serializable, Serializable> map = new HashMap<>(16);
        List<ProfessionTemplate> templateList = new ArrayList<>();
        ProfessionTemplate professionTemplate = new ProfessionTemplate();
        professionTemplate.setCode("0504");
        professionTemplate.setName("教育技术学");
        professionTemplate.setSchoolLength("4");
        professionTemplate.setNature("本科");
        professionTemplate.setAcademyName("物理与电子信息学院");
        professionTemplate.setRemark("导入数据模板");
        templateList.add(professionTemplate);
        //sheet的名字
        map.put(SHEET_NAME, "专业信息");
        //需要导入的字段
        map.put(COLUMNS,   new String[]{"code", "name", "schoolLength", "nature", "academyName", "remark"});
        //表格的标题
        map.put(TITLE, "专业信息");
        map.put(NAME, "专业信息模板");
        map.put(DATA_LIST, (Serializable) templateList);
        try {
            ExcelUtil.exportExcel(map, response);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 批量导入专业信息
     * @param multipartFile
     * @param request
     * @param response
     * @return
     * @author 杨燕梅
     * @since 2.0.0 2018-11-30 11:25:48
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ItooResult importTemplate(MultipartFile multipartFile, HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("UTF-8");
        try {
            //校验文件是否存在
            String fileName = multipartFile.getOriginalFilename();
            if (fileName == null) {
                log.error("导入失败,fileName is null!");
                return ItooResult.build(ItooResult.FAIL, "传入的文件为空！");
            }
            //EXCEL解析成List
            Map<Serializable, Serializable> map = new HashMap<>(4);
            map.put(SHEET_NAME, "专业信息");
            map.put(CLASS, ProfessionTemplate.class);
            List<ProfessionTemplate> professionTemplateList = ExcelUtil.importExcel(Objects.requireNonNull(fileName), map, request, response);
            if (professionTemplateList.size()== 0) {
                return ItooResult.build(ItooResult.FAIL, "导入的数据为空，请填写！");
            }
            //定义导入的错误数据集合并存redis中形式的<String,ProfessionTemplate>
            List<ProfessionTemplate> errorPTList = new ArrayList<>();
            String errorListId = BaseUuidUtils.base58Uuid();
            Long size = redisTemplate.opsForZSet().size(errorListId);
            size = size == null ? 0L : size;
            //循环处理数据
            for (ProfessionTemplate excelPT : professionTemplateList) {
                if (!this.verify(excelPT)) {
                    ProfessionTemplate professionT = new ProfessionTemplate();
                    BeanUtils.copyProperties(excelPT, professionT);
                    errorPTList.add(professionT);
                    redisTemplate.opsForZSet().add(errorListId, professionT, size + 1);
                    continue;
                }
                ProfessionEntity professionEntity = new ProfessionEntity();
                //将导入内容放到entity中对应的属性中去
                BeanUtils.copyProperties(excelPT,professionEntity);
                //专业编码
                professionEntity.setCode(excelPT.getCode());
                //专业名称
                professionEntity.setName(excelPT.getName());
                //学制
                professionEntity.setSchoolLength(excelPT.getSchoolLength());
                //备注
                professionEntity.setRemark(excelPT.getRemark());
                this.save(professionEntity);
                this.saveToAuth(professionEntity);
            }
            //不符合条件的信息返回
            if (!CollectionUtils.isEmpty(errorPTList)) {
                return ItooResult.build("0001", "部分导入失败", errorListId);
            }
        } catch (Exception e) {
            return ItooResult.build(ItooResult.FAIL, "导入数据异常！", e);
        }
        return ItooResult.build(ItooResult.SUCCESS, "导入数据成功！");
    }

    /**
     * 判断批量导入的信息是否符合要求
     *
     * @param professionTemplate 需要导入的信息
     * @return boolean 导入的字段是否为空
     * @author 杨燕梅
     * @since 2.0.0 2018-12-2 10:39:14
     */
    private boolean verify( ProfessionTemplate professionTemplate) {
        //判断专业代码是否填写
        if (StringUtils.isEmpty(professionTemplate.getCode())) {
            professionTemplate.setFailReason("专业代码未填写");
            log.warn("导入失败,专业代码未填写,excelProfessionEntity-{}", professionTemplate);
            return false;
        }
        //判断专业名称是否填写
        if (StringUtils.isEmpty(professionTemplate.getName())) {
            professionTemplate.setFailReason("专业名称未填写");
            log.warn("导入失败,专业名称未填写,excelProfessionEntity-{}", professionTemplate);
            return false;
        }
        //判断学制是否填写
        if (StringUtils.isEmpty(professionTemplate.getSchoolLength())) {
            professionTemplate.setFailReason("学制未填写");
            log.warn("导入失败,学制未填写,excelProfessionEntity-{}", professionTemplate);
            return false;
        }
        //判断专业是否重复
        if (!CollectionUtils.isEmpty(professionDao.queryByCodeAndNameExist(professionTemplate.getCode(),professionTemplate.getName()))){
            professionTemplate.setFailReason("专业已存在");
            log.warn("导入失败,专业已存在,excelProfessionEntity-{}", professionTemplate);
            return false;
        }
        //判断学院id是否获取到
        String academyId = academyService.queryAcademyIdByName(professionTemplate.getAcademyName());
        if(StringUtils.isEmpty(academyId)){
            professionTemplate.setFailReason("学院不存在");
            log.warn("导入失败,学院不存在,excelProfessionEntity-{}", professionTemplate);
            return false;
        }
        //把学院名称转成学院Id存入数据库
        professionTemplate.setAcademyId(academyId);
        //判断专业性质(专业层次)是否获取到
        String nature =  professionService.queryNatureIdByName(professionTemplate.getNature());
        if(StringUtils.isEmpty(nature)){
            professionTemplate.setFailReason("专业性质不存在");
            log.warn("导入失败,专业性质不存在,excelProfessionEntity-{}", professionTemplate);
            return false;
        }
        //把专业性质（专业层次）从汉字（本科，专科，专升本）转成相应代码存入数据库
        professionTemplate.setNature(nature);
        return true;
    }

    /**
     * 根据errorListId导出未成功导入的信息
     *
     * @param response    响应
     * @param errorListId 为成功导入的分组id
     * @return 导出结果
     * @author 杨燕梅
     * @since 1.0.0 2018-12-2 10:37:51
     */
    @Override
    public boolean exportErrorList(String errorListId, HttpServletResponse response){
        //redis取出没有成功导入的专业信息
        Set set = redisTemplate.opsForZSet().range(errorListId, 0, -1);
        List<ProfessionTemplate> professionTemplateList=new ArrayList<>(set);
        //清空redis数据
        redisTemplate.delete(errorListId);
        //导出没有成功导入的专业信息
        if(professionTemplateList.size()==0){
            return false;
        }
        Map<Serializable, Serializable> errorMap = new HashMap<>(16);
        errorMap.put(NAME, "未导入的专业信息");
        errorMap.put(SHEET_NAME, "专业信息");
        errorMap.put(TITLE, "未导入的专业信息");
        errorMap.put(COLUMNS, new String[]{"code", "name", "schoolLength", "nature", "academyName", "remark", "failReason"});
        errorMap.put(DATA_LIST, (Serializable) professionTemplateList);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 根据专业性质（专业层次）汉字（本科，专科，专升本）查询相应代码
     * @param name  专业性质（专业层次）汉字
     * @return 专业层次的相应代码
     * @author 杨燕梅
     * @since 2.0.0 2018-12-2 20:28:43
     */
    @Override
    public String queryNatureIdByName(String name) {
        return professionDao.queryNatureIdByName(name);
    }

    /**
     * 根据专业名称获取专业Id作为班级的专业Id
     * @param professionName  专业名称
     * @return 专业Id
     * @author 杨燕梅
     * @since 2.0.0 2018-12-5 20:46:06
     */
    @Override
    public String queryProfessionIdByName(String professionName) {
        return professionDao.queryProfessionIdByName(professionName);
    }

    /**
     * 根据专业代码和专业名称查询专业是否已存在
     *
     * @param code   专业代码
     * @param name   专业名称
     * @return 专业信息
     * @author 杨燕梅
     * @since 2.0.0 2018-12-20 09:49:06
     */
    @Override
    public List<ProfessionEntity>queryByCodeAndNameExist(String code, String name){
        return professionDao.queryByCodeAndNameExist(code,name);
    }

    /**
     * 将数据保存到权限中去
     *
     * @param professionEntity
     * @author 李建帅
     * @since 2.0.0 2018-12-9 19:18:10
     */
    @Override
    public void saveToAuth(ProfessionEntity professionEntity){
//        List<OrganizationEntity> organizationEntityList = new ArrayList<>();
//        OrganizationEntity organizationEntity = new OrganizationEntity();
//        organizationEntity.setId(professionEntity.getId());
//        organizationEntity.setOrganizationName(professionEntity.getName());
//        organizationEntity.setPId(professionEntity.getAcademyId());
//        organizationEntity.setCompanyId("lfsfxy111222");
//        organizationEntityList.add(organizationEntity);
//        organizationFacade.synchroOrganization(organizationEntityList);
//
//        try {
//            organizationFacade.synchroOrganization(organizationEntityList);
//        } catch (Exception e) {
//            log.error("将组织机构信息同步到权限中心失败！", e);
//        }
    }

    @Override
    public List<ProfessionEntity> findByAcademyId(String academyId) {
        return professionDao.findByAcademyId(academyId);
    }

    @Override
    public List<ProfessionModel> inquirySpecialty(String academyId) {
        return professionDao.inquirySpecialty(academyId, YearAcquisitionUtil.yearAcquisition().get("minSession"), YearAcquisitionUtil.yearAcquisition().get("maxSession"));
    }
}